from core.DataStruct import Sample
import math
import numpy as np
import matplotlib.pyplot as plt
import copy

from PyQt5 import QtCore

class ColorCombine(QtCore.QObject):

    colorCombineSignal = QtCore.pyqtSignal()
    colorCorrectSignal = QtCore.pyqtSignal()
    colorCombineStepSignal = QtCore.pyqtSignal(int, float, list)
    colorCorrectStepSignal = QtCore.pyqtSignal(int, float, list, list)

    """
    配色
    """
    def __init__(self, group, formula, config):
        super(ColorCombine, self).__init__()
        self.group = group                              # 色料组；
        self.formula = formula                          # 配方；
        self.totalQuality = 20
        self.cfg = config
        self.base = None
        self.deltaXYZ = None
        self.preRecipe = None
        self.factor = [1] * 32

    def setStandardSmp(self, smp):
        self.standardSmp = smp

    def calcConcBySpider(self):
        """
        蚁群算法求取最优；
        :param conc:
        :return:
        """
        print("粒子群配色")
        C1 = C2 = 2     # 学习因子；
        maxIter = 100      # 迭代次数；
        curIter = maxIter  # 当前迭代数；
        nVar = 4            # 自变量；
        spiderNum = 100      # 粒子数；
        wmax = 0.9             # 惯性因子；
        wmin = 0.4
        vmax = 5.0          # 最大飞行速度；
        v = 2 * np.random.rand(spiderNum, nVar)               # 初始飞行速度；
        x = 10 * np.random.rand(spiderNum, nVar)             # 初始位置；
        for i in range(spiderNum):                           # 第一个要大；
            x[i, 0] = 100 - x[i, 0]
        personalBest = copy.deepcopy(x)                                      # 粒子最好记录；
        personalBestVal = [10000000] * spiderNum                     # 粒子最好值；
        f = lambda x: self.__critionFunction(x, self.base)         # 计算当前的
        fval = [0] * spiderNum                                # 当前粒子的值；
        globalbestVal = 0                                      # 全局最好值；
        globalbestX = None                                     # 全局最好位置;
        # 初始化；
        while curIter > 0:
            #迭代;
            for i in range(spiderNum):
                tmp = copy.deepcopy(x[i, :])
                fval[i] = f(tmp)                          # 计算当前粒子位置的色差；
                if fval[i] < personalBestVal[i]:
                    personalBestVal[i] = fval[i]
                    personalBest[i, :] = tmp
            # 求最好的值，以及最好的粒子；
            globalbestVal = np.min(personalBestVal)                # 最好的值；
            tmpIdx = personalBestVal.index(globalbestVal)          # 最好的粒子；
            globalbestX = copy.deepcopy(personalBest[tmpIdx, :])
            if globalbestVal < 0.01:
                break
            if len(globalbestX) == self.formula.nComp:
                for j in range(self.formula.nComp):
                    self.formula.colorantsComp[j].quality = globalbestX[j]
            self.colorCombineStepSignal.emit(maxIter - curIter, globalbestVal, list(globalbestX))
            # 更新速度以及位置；
            for i in range(spiderNum):
                w = (wmax - wmin) * (maxIter - curIter)/maxIter + wmin
                v[i, :] = w * v[i, :] + C1 * np.random.rand() * (personalBest[i, :] - x[i, :]) + \
                    C2 * np.random.rand() * (globalbestX - x[i, :])
                for j in range(nVar):
                    if v[i, j] > vmax:
                        v[i, j] = vmax
                    if v[i, j] < -vmax:
                        v[i, j] = -vmax
                x[i, :] = x[i, :] + v[i, :]
            curIter -= 1
        if len(globalbestX) == self.formula.nComp:
            for j in range(self.formula.nComp):
                self.formula.colorantsComp[j].quality = globalbestX[j]
        self.colorCombineSignal.emit()
        return globalbestX

    def calcAddRecipeBySpider(self):
        """
        粒子群算法， 计算得到添加量；
        :param preRecipe:
        :param base:
        :return:
        """
        C1 = C2 = 2  # 学习因子；
        maxIter = 100  # 迭代次数；
        curIter = maxIter  # 当前迭代数；
        nVar = 4  # 自变量；
        spiderNum = 50  # 粒子数；
        wmax = 0.9  # 惯性因子；
        wmin = 0.4
        vmax = 5.0  # 最大飞行速度；
        v = 2 * np.random.rand(spiderNum, nVar)  # 初始飞行速度；
        x = 10 * np.random.rand(spiderNum, nVar)  # 初始位置；
        for i in range(spiderNum):  # 第一个要大；
            x[i, 0] = 10 - x[i, 0]
        personalBest = copy.deepcopy(x)  # 粒子最好记录；
        personalBestVal = [10000000] * spiderNum  # 粒子最好值；
        f = lambda xyz, m, n, b, coef: self.__critiionFunctionOfCorrect(xyz, m, n, b, coef)  # 计算当前的
        fval = [0] * spiderNum  # 当前粒子的值；
        globalbestVal = 0  # 全局最好值；
        globalbestX = None  # 全局最好位置;
        # 初始化；
        while curIter > 0:
            # 迭代;
            for i in range(spiderNum):
                tmp = copy.deepcopy(x[i, :])
                fval[i] = f(self.deltaXYZ, self.preRecipe, tmp, self.base, self.factor)  # 计算当前粒子位置的色差；
                if fval[i] < personalBestVal[i]:
                    personalBestVal[i] = fval[i]
                    personalBest[i, :] = tmp
            # 求最好的值，以及最好的粒子；
            globalbestVal = np.min(personalBestVal)  # 最好的值；
            tmpIdx = personalBestVal.index(globalbestVal)  # 最好的粒子；
            globalbestX = copy.deepcopy(personalBest[tmpIdx, :])
            if globalbestVal < 0.01:
                break
            if len(globalbestX) == self.formula.nComp:
                for j in range(self.formula.nComp):
                    self.formula.colorantsComp[j].quality = globalbestX[j]
            self.colorCorrectStepSignal.emit(maxIter - curIter, globalbestVal, list(globalbestX), [])
            # 更新速度以及位置；
            for i in range(spiderNum):
                w = (wmax - wmin) * (maxIter - curIter) / maxIter + wmin
                v[i, :] = w * v[i, :] + C1 * np.random.rand() * (personalBest[i, :] - x[i, :]) + \
                          C2 * np.random.rand() * (globalbestX - x[i, :])
                for j in range(nVar):
                    if v[i, j] > vmax:
                        v[i, j] = vmax
                    if v[i, j] < -vmax:
                        v[i, j] = -vmax
                x[i, :] = x[i, :] + v[i, :]
            curIter -= 1
        newRecipe = [0] * len(self.preRecipe)
        ratio = 0
        addRecipe = [0] * len(self.preRecipe)
        for i in range(len(self.preRecipe)):
            newRecipe[i] = self.preRecipe[i] + globalbestX[i]
            if newRecipe[i] <= 0:
                continue
            if self.preRecipe[i] / newRecipe[i] > ratio:
                ratio = self.preRecipe[i] / newRecipe[i]
        for i in range(len(self.preRecipe)):
            newRecipe[i] *= ratio
            addRecipe[i] = newRecipe[i] - self.preRecipe[i]
        print(newRecipe)
        print(addRecipe)
        print(self.__critionFunction(newRecipe, self.base))
        self.colorCorrectStepSignal.emit(maxIter - curIter, globalbestVal, newRecipe, addRecipe)
        if len(globalbestX) == self.formula.nComp:
            for j in range(self.formula.nComp):
                self.formula.colorantsComp[j].quality = globalbestX[j]
        self.colorCorrectSignal.emit()

    def __critionFunction(self, res, base):
        """
        判决函数；
        :param res:
        :param base:
        :return:
        :return:
        """
        for i in range(len(res)):
            if res[i] < 0:
                res[i] = 0
            if res[i] > 100:
                res[i] = 100
        tmpSum = sum(res)
        for i in range(len(res)):
            res[i] *= self.totalQuality / tmpSum
        for i in range(1, self.formula.nComp):  # 其他色料的；
            self.formula.colorantsComp[i].colorants.calcKSBySw(res[i] / self.totalQuality * 100)

        # 算R0;
        tmpSD = [0] * 32  # 计算SD;
        tmpR0 = [0] * 32
        tmpRint = [0] * 32
        tmpKByS = [0] * 32
        for i in range(32):
            tmpSD[i] = res[0]/self.totalQuality * self.formula.colorantsComp[0].colorants.SD[i]
            for j in range(1, self.formula.nComp):
                tmpSD[i] += res[j] / self.totalQuality * self.formula.colorantsComp[j].colorants.S_by_Sw[i] * \
                            self.formula.colorantsComp[0].colorants.SD[i]
            # tmpSD[i] = self.formula.colorantsComp[0].colorants.SD[i]                # 测试；
        for i in range(32):
            sum1 = 0
            sum2 = 0
            for j in range(self.formula.nComp):
                sum1 += res[j] * self.formula.colorantsComp[j].colorants.K_by_Sw[i]
                sum2 += res[j] * self.formula.colorantsComp[j].colorants.S_by_Sw[i]
            tmpKByS[i] = sum1 / sum2                                                    # 应该是一样的；
            if tmpKByS[i] < 0:
                return 10000
            tmpRint[i] = 1.0 + tmpKByS[i] - math.sqrt(tmpKByS[i] * tmpKByS[i] + 2 * tmpKByS[i])
            try:
                tmpR0[i] = (1 - math.pow(math.e, tmpSD[i] * (1 / tmpRint[i] - tmpRint[i]))) / (
                        tmpRint[i] - 1 / tmpRint[i] * math.pow(math.e, tmpSD[i] * (1 / tmpRint[i] - tmpRint[i])))
            except:
                tmpR0[i] = tmpR0[i - 1]

        # 测试；
        tmpTest = [0] * 32
        tmpSub = [0] * 32
        for i in range(32):
            tmpRg = base.ref[i]
            tmpRef = self.standardSmp.ref[i]
            tmpA = (tmpRg + tmpR0[i] - 2 * tmpRg * tmpR0[i]) / (1 - tmpRg * tmpR0[i])
            tmpRgR0 = 2 * tmpRg * tmpR0[i] / (1 - tmpRg * tmpR0[i])
            tmpRint2 = tmpA - tmpRgR0 * tmpKByS[i]
            # tmpK2= (self.cfg.gKa2 + self.cfg.gKb2 * tmpRint2)/(self.cfg.gKc2 + self.cfg.gKd2 * tmpRint2)
            # tmpK3= 1.0- self.group.K1 - tmpK2
            # tmpCalRef = (self.group.K1 + tmpK3 * tmpRint2)/(1 - tmpK2 * tmpRint2)
            tmpTest[i] = tmpRef - tmpRint2
            tmpSub[i] = abs(tmpTest[i])
        deltaX = 0
        deltaY = 0
        deltaZ = 0
        for i in range(32):
            deltaX += self.standardSmp.xsysns[i][0] * tmpTest[i]
            deltaY += self.standardSmp.xsysns[i][1] * tmpTest[i]
            deltaZ += self.standardSmp.xsysns[i][2] * tmpTest[i]
        deltaE = (1 - self.cfg.weight) * math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) + self.cfg.weight * sum(tmpSub)
        return deltaE

    def __critiionFunctionOfCorrect(self, deltaXYZ, preRecipe, addRecipe, base, coef):
        """
        用于修色的判决函数；
        :param deltaXYZ:
        :param preRecipe:
        :param addRecipe:
        :param base:
        :return:
        """
        res = [0] * len(preRecipe)
        for i in range(len(addRecipe)):
            if addRecipe[i] < 0:
                addRecipe[i] = 0
            if addRecipe[i] > 100:
                addRecipe[i] = 100
            res[i] = preRecipe[i] + addRecipe[i]
        tmpSum = sum(res)
        for i in range(len(res)):
            res[i] *= self.totalQuality/tmpSum
        for i in range(1, self.formula.nComp):  # 其他色料的；
            self.formula.colorantsComp[i].colorants.calcKSBySw(res[i] / self.totalQuality * 100)

        # 算R0;
        tmpSD = [0] * 32  # 计算SD;
        tmpR0 = [0] * 32
        tmpRint = [0] * 32
        tmpKByS = [0] * 32
        for i in range(32):
            for j in range(self.formula.nComp):
                tmpSD[i] += res[j] / self.totalQuality * self.formula.colorantsComp[j].colorants.S_by_Sw[i] * \
                            self.formula.colorantsComp[0].colorants.SD[i]
        for i in range(32):
            sum1 = 0
            sum2 = 0
            for j in range(self.formula.nComp):
                sum1 += res[j] * self.formula.colorantsComp[j].colorants.K_by_Sw[i]
                sum2 += res[j] * self.formula.colorantsComp[j].colorants.S_by_Sw[i]
            tmpKByS[i] = sum1 / sum2 / coef[i]
            if tmpKByS[i] < 0:
                return 10000
            tmpRint[i] = 1.0 + tmpKByS[i] - math.sqrt(tmpKByS[i] * tmpKByS[i] + 2 * tmpKByS[i])
            try:
                tmpR0[i] = (1 - math.pow(math.e, tmpSD[i] * (1 / tmpRint[i] - tmpRint[i]))) / (
                        tmpRint[i] - 1 / tmpRint[i] * math.pow(math.e, tmpSD[i] * (1 / tmpRint[i] - tmpRint[i])))
            except:
                tmpR0[i] = tmpR0[i - 1]

        # 测试；
        tmpTest = [0] * 32
        tmpSub = [0] * 32
        for i in range(32):
            tmpRg = base.ref[i]
            tmpRef = self.standardSmp.ref[i]
            tmpA = (tmpRg + tmpR0[i] - 2 * tmpRg * tmpR0[i]) / (1 - tmpRg * tmpR0[i])
            tmpRgR0 = 2 * tmpRg * tmpR0[i] / (1 - tmpRg * tmpR0[i])
            tmpRint2 = tmpA - tmpRgR0 * tmpKByS[i]
            # tmpCalRef = (self.group.K1 + (1 - self.group.K1 - (self.cfg.gKa2 + self.cfg.gKb2 * tmpRint)/
            # (self.cfg.gKc2 + self.cfg.gKd2 * tmpRint)) * tmpRint)/(1 - (self.cfg.gKa2 + self.cfg.gKb2 * tmpRint)/(self.cfg.gKc2 + self.cfg.gKd2 * tmpRint) * tmpRint)
            tmpTest[i] = tmpRint2
            tmpSub[i] = abs(tmpRef - tmpRint2)
        tmpX = 0
        tmpY = 0
        tmpZ = 0
        for i in range(32):
            tmpX += self.standardSmp.xsysns[i][0] * tmpTest[i]
            tmpY += self.standardSmp.xsysns[i][1] * tmpTest[i]
            tmpZ += self.standardSmp.xsysns[i][2] * tmpTest[i]
        tmpX -= deltaXYZ[0]                                           # 消掉现有的色差；
        tmpY -= deltaXYZ[1]
        tmpZ -= deltaXYZ[2]
        deltaX = self.standardSmp.xyz[0] - tmpX
        deltaY = self.standardSmp.xyz[1] - tmpY
        deltaZ = self.standardSmp.xyz[2] - tmpZ
        deltaE = (1- self.cfg.weight) * math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) + self.cfg.weight * sum(tmpSub)
        return deltaE


    ###############################################################################################################
    #     下面的几个函数没用；
    ###############################################################################################################
    def calcDeltaE(self, res, base):
        print(self.__critionFunction(res, base))

    def calcRefByConc(self, formula, testConc, K1, pureWhite, base, recipeSample):
        """
        计算指定浓度下的反射率；  这里用于计算调整因子；
        :param testConc:
        :param K1:
        :param pureWhite:
        :param base:
        :return:
        """
        factor = [1.0] * 32                           # 调节因子；
        for k in range(1, 4, 1):
            tmpConc = testConc[k] / sum(testConc) * 100
            if tmpConc == 0:
                continue
            formula.colorantsComp[k].colorants.calcKSBySw(tmpConc)                     # 计算对应浓度的单位吸收系数和单位散射系数；    采用插值；

        for k in range(4):
            formula.colorantsComp[k].quality = testConc[k]
        tmpRef = [0] * 32           # 当前浓度的反射率；
        error = [100] * 32
        for i in range(32):                         # 计算32个factor；
            iter = 100
            while math.fabs(error[i]) > 0.001 and iter > 0:
                tmpSum1 = 0
                tmpSum2 = 0
                for k in range(formula.nComp):
                    tmpSum1 += testConc[k] * formula.colorantsComp[k].colorants.K_by_Sw[i]
                    tmpSum2 += testConc[k] * formula.colorantsComp[k].colorants.S_by_Sw[i]
                tmpKByS = tmpSum1/tmpSum2 * factor[i]
                tmpRint = 1.0 + tmpKByS - math.sqrt(tmpKByS * tmpKByS + 2 * tmpKByS)                    # 计算得到内放射率；
                tmpSD = 0
                for k in range(formula.nComp):
                    tmpSD += testConc[k]/sum(testConc) * formula.colorantsComp[k].colorants.S_by_Sw[i] * pureWhite.SD[i]
                tmp1 = (base.ref[i] - tmpRint)/(tmpRint * tmpRint)
                tmp2 = (1/tmpRint - base.ref[i]) * math.pow(math.e, tmpSD * (1/tmpRint - tmpRint))
                tmp3 = base.ref[i] - tmpRint + tmp2
                tmpRef[i] = tmpRint * (tmp1 + tmp2)/tmp3
                K2 = (self.cfg.gKa2 + self.cfg.gKb2 * tmpRef[i]) / (self.cfg.gKc2 + self.cfg.gKd2 * tmpRef[i])
                K3 = 1.0 - K1 - K2
                tmpRef[i] = (K1 + K3 * tmpRef[i]) / (1 - K2 * tmpRef[i])
                error[i] = tmpRef[i] - recipeSample.ref[i]
                if math.fabs(error[i]) < 0.001:
                    break
                if error[i] > 0:
                    factor[i] *= 1.01
                else:
                    factor[i] *= 0.99
                iter = iter - 1
        return factor


    def calcInitConc(self):
        """
        计算初始值；          四色；
        :param conc:
        :return:
        """
        # 给K/Sw, S/Sw赋初始值；    梯度所有大于0的K/Sw, S/Sw取平均；
        for i in range(1, self.formula.nComp):
            for k in range(32):
                num = 0
                for j in range(len(self.formula.colorantsComp[i].colorants.step)):                                           # 其他色料；
                    tmpKBySw = self.formula.colorantsComp[i].colorants.step[j].K_by_Sw[k]
                    tmpSBySw = self.formula.colorantsComp[i].colorants.step[j].S_by_Sw[k]
                    if tmpSBySw < 0:
                        continue
                    self.formula.colorantsComp[i].colorants.K_by_Sw[k] += tmpKBySw
                    self.formula.colorantsComp[i].colorants.S_by_Sw[k] += tmpSBySw
                    num += 1
                self.formula.colorantsComp[i].colorants.K_by_Sw[k] /= num
                self.formula.colorantsComp[i].colorants.S_by_Sw[k] /= num

        a = [0] * 3
        b = [0] * 3
        c = [0] * 3
        d = [0] * 3
        e = [0] * 3
        for j in range(3):
            for i in range(32):
                tmp = self.standardSmp.xsysns[i][j] * (1 - (self.standardSmp.K_by_S[i] + 1)/math.sqrt((self.standardSmp.K_by_S[i] + 1) * (self.standardSmp.K_by_S[i] + 1) - 1))
                b[j] += tmp * self.formula.colorantsComp[0].colorants.K_by_Sw[i]
                a[j] += tmp * self.standardSmp.K_by_S[i]
                c[j] += tmp * self.formula.colorantsComp[1].colorants.K_by_Sw[i]
                d[j] += tmp * self.formula.colorantsComp[2].colorants.K_by_Sw[i]
                e[j] += tmp * self.formula.colorantsComp[3].colorants.K_by_Sw[i]
        A = np.zeros((4, 4))
        B = np.zeros((4, 1))
        for i in range(3):
            A[i][0] = a[i] - b[i]
            A[i][1] = -c[i]
            A[i][2] = -d[i]
            A[i][3] = -e[i]
            B[i][0] = 0
        A[3][0] = 1
        A[3][1] = 1
        A[3][2] = 1
        A[3][3] = 1
        B[3][0] = self.totalQuality

        ATA = A.T.dot(A)
        ATB = A.T.dot(B)
        res = np.linalg.inv(ATA).dot(ATB)
        for i in range(len(res)):
            if res[i] < 0:
                res[i] = 0
        return res

    def calcConc(self, conc, base):
        """
        计算配方   精修；
        :param conc:
        :param base:        基底；
        :return:
        """
        iter = 100
        res = conc
        for it in range(iter):
            tmpSum = sum(res)
            for i in range(len(res)):
                res[i] *= self.totalQuality / tmpSum
                for i in range(32):                                             # 初始化白的；
                    self.formula.colorantsComp[0].colorants.K_by_Sw[i] = res[0]/self.totalQuality * self.formula.colorantsComp[0].colorants.K_by_S[i]
                    self.formula.colorantsComp[0].colorants.S_by_Sw[i] = res[0]/self.totalQuality
            for i in range(0, self.formula.nComp):                                 # 其他色料的；
                self.formula.colorantsComp[i].colorants.calcKSBySw(res[i]/self.totalQuality * 100)

            # 算R0;
            tmpSD = [0] * 32                    # 计算SD;
            tmpR0 = [0] * 32
            tmpRint = [0] * 32
            tmpKByS = [0] * 32
            for i in range(32):
                tmpSD[i] = res[0] / self.totalQuality * self.formula.colorantsComp[0].colorants.SD[i]
                for j in range(1, self.formula.nComp):
                    tmpSD[i] += res[j] / self.totalQuality * self.formula.colorantsComp[j].colorants.S_by_Sw[i] * self.formula.colorantsComp[0].colorants.SD[i]
            for i in range(32):
                sum1 = 0
                sum2 = 0
                for j in range(self.formula.nComp):
                    sum1 += res[j] * self.formula.colorantsComp[j].colorants.K_by_Sw[i]
                    sum2 += res[j] * self.formula.colorantsComp[j].colorants.S_by_Sw[i]
                tmpKByS[i] = sum1/sum2
                tmpRint[i] = 1.0 + tmpKByS[i] - math.sqrt(tmpKByS[i] * tmpKByS[i] + 2 * tmpKByS[i])
                try:
                    tmpR0[i] = (1 - math.pow(math.e, tmpSD[i] * (1/tmpRint[i] - tmpRint[i]))) / (tmpRint[i] - 1/tmpRint[i] * math.pow(math.e, tmpSD[i] * (1/tmpRint[i] - tmpRint[i])))
                except:
                    tmpR0[i] = tmpR0[i-1]
            A = np.zeros((4, 4))
            B = np.zeros((4, 1))
            D = np.zeros((4, 4))
            DINV = np.zeros((4, 4))
            for j in range(3):
                for i in range(32):
                    tmpRg = base.ref[i]
                    tmpRef = self.standardSmp.actualRef[i]
                    tmpA = tmpRef + (tmpRg + tmpR0[i] -2 * tmpRg * tmpR0[i])/(tmpRg * tmpR0[i] - 1)
                    tmp = self.standardSmp.xsysns[i][j]
                    tmpRgR0  = 2 * tmpRg * tmpR0[i] / (tmpRg * tmpR0[i] - 1)
                    A[j][0] += tmp * (tmpA - tmpRgR0 * self.formula.colorantsComp[0].colorants.K_by_Sw[i])
                    A[j][1] += tmp * (tmpA * self.formula.colorantsComp[1].colorants.S_by_Sw[i] - tmpRgR0 * self.formula.colorantsComp[1].colorants.K_by_Sw[i])
                    A[j][2] += tmp * (tmpA * self.formula.colorantsComp[2].colorants.S_by_Sw[i] - tmpRgR0 * self.formula.colorantsComp[2].colorants.K_by_Sw[i])
                    A[j][3] += tmp * (tmpA * self.formula.colorantsComp[3].colorants.S_by_Sw[i] - tmpRgR0 * self.formula.colorantsComp[3].colorants.K_by_Sw[i])
            for k in range(4):
                A[3][k] = 1
            B[3][0] = self.totalQuality

            for i in range(4):
                D[i][i] = A[i][i]
                DINV[i][i] = 1/A[i][i]
            LU = A - D
            res = - DINV.dot(LU).dot(res) + DINV.dot(B)
            print(res)
            for i in range(len(res)):
                if res[i] < 0.001:
                    res[i] = 0
        tmpSum = sum(res)
        for i in range(len(res)):
            res[i] *= self.totalQuality / tmpSum
        print(self.__critionFunction(res, base))
        return res

    def calcRef(self, conc):
        """
        反算总反射率；
        :param conc:
        :param self.formula.colorantsComp[0].colorants:
        :param colorants:
        :return:
        """
        KbyS = [0] * 32
        for i in range(32):
            tmp1 = conc[0] * self.formula.colorantsComp[0].colorants.K_by_Sw[i] + conc[1] * self.formula.colorantsComp[1].colorants.K_by_Sw[i] + conc[2] * \
                   self.formula.colorantsComp[2].colorants.K_by_Sw[i] + conc[3] * self.formula.colorantsComp[3].colorants.K_by_Sw[i]
            tmp2 = conc[0] * self.formula.colorantsComp[0].colorants.S_by_Sw[i] + conc[1] * self.formula.colorantsComp[1].colorants.S_by_Sw[i] + conc[2] * \
                   self.formula.colorantsComp[2].colorants.S_by_Sw[i] + conc[3] * self.formula.colorantsComp[3].colorants.S_by_Sw[i]
            KbyS[i] = float(tmp1 / tmp2)

        rint = [0] * 32
        for i in range(32):
            rint[i] = 1.0 + KbyS[i] - math.sqrt(KbyS[i] * KbyS[i] + 2 * KbyS[i])

        newSmp = Sample()
        for i in range(32):
            K2 = (self.cfg.gKa2 + self.cfg.gKb2 * rint[i]) / (self.cfg.gKc2 + self.cfg.gKd2 * rint[i])
            K3 = 1 - K2 - self.group.K1
            newSmp.ref[i] = (self.group.K1 + K3 * rint[i])/(1 - K2 * rint[i])

        self.standardSmp.calcXYZ()
        self.standardSmp.xyzToLab()
        newSmp.calcXYZ()
        newSmp.xyzToLab()
        newSmp.calcDeltaE(self.standardSmp)
        print(newSmp.deltaE)

        fig1 = plt.figure(1, figsize=(12, 10))
        x = range(32)
        plt.plot(x, newSmp.ref, linestyle='-', alpha=0.8, color='r')
        plt.plot(x, self.standardSmp.ref, linestyle='-', alpha=0.8, color='g')
        plt.show()

